#include "common.h"

int port;
char *filename;
void server_routine();
void* sender(void*);

int main(int argc, char* argv[]) {
	if (argc < 3) {
		printf("Usage:\n  %s <filename> <port>\n", argv[0]);
		return 1;
	}

	filename = argv[1];
	port = atoi(argv[2]);

	server_routine();
}

void server_routine() {
	int listenfd, clientfd, ret, reuse;
	int *fd;
	struct sockaddr_in servaddr, cliaddr;
	socklen_t cliaddrlen;
	pthread_t th;

	servaddr = resolve("0", port);

	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd < 0) ERR_EXIT("socket");
	reuse = 1;
	ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 
  if (ret < 0) ERR_EXIT("reuse");
	
  ret = bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
  if (ret < 0) ERR_EXIT("bind");

  ret = listen(listenfd, 5);
  if (ret < 0) ERR_EXIT("listen");

	while(1) {
		cliaddrlen = sizeof(cliaddr);
		clientfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen);
		if (clientfd < 0) ERR_EXIT("accept");
		printf("%s:%d come in\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

		fd = (int*)malloc(sizeof(fd));
		*fd = clientfd;
		ret = pthread_create(&th, NULL, sender, (void*)fd);
		if (ret != 0) {
			errno = ret;
			ERR_EXIT("pthread_create");
		}
	}
}

void* sender(void* arg) {
	int nr, ret;
	int clientfd = *(int*)arg;
	FILE* fp = fopen(filename, "rb");
	char buf[8192];

	sleep(10);

	puts("Start sending...");
	while((nr = fread(buf, 1, sizeof(buf), fp)) != 0) {
		ret = writen(clientfd, buf, nr);
		if (ret < 0) ERR_EXIT("writen");
	}
	puts("Finish sending file");

	fclose(fp);
	
	// 这里不能用 close，因为对方很可能正在阻塞在 write 上或者正在通过 write 写数据。
	shutdown(clientfd, SHUT_WR);

	while(read(clientfd, buf, sizeof(buf)));

	free(arg);
	puts("All done");
}
